package com.sinosoft.brokerchannel.base.handler;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.sinosoft.brokerchannel.base.annotation.MyResponseBody;
import com.sinosoft.brokerchannel.base.bins.Template;
import com.sinosoft.brokerchannel.base.filters.JacksonFilter;
import com.sinosoft.brokerchannel.base.server.InterfaceConfigeService;
import com.sinosoft.brokerchannel.base.utile.AESUtil;
import com.sinosoft.brokerchannel.base.utile.JacksonSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @类描述:自定义视图handler
 */
public class ViewHandler implements HandlerMethodReturnValueHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private InterfaceConfigeService interfaceConfigeService;

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // 使用了自定义视图注解的时候拦截处理
        return returnType.getMethodAnnotation(MyResponseBody.class) != null;
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        //设置这个就是最终的处理类了，处理完不再去找下一个类进行处理
        mavContainer.setRequestHandled(true);
        //获得注解并执行filter方法 最后返回
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        //请求类型
        String contentType = request.getContentType();
        response.setContentType(contentType);
        JacksonSerializer viewSerializer;
        ObjectMapper mapper;
        if (contentType.contains("xml")) {//xml输出
            mapper = new XmlMapper();
        } else {//json输出
            mapper = new ObjectMapper();
        }

        //序列化对象时去除空值
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        viewSerializer = new JacksonSerializer(mapper, new JacksonFilter());
        //添加过滤器
        List<Template> templates = interfaceConfigeService.getTemplate((String) request.getAttribute("channelCode"), returnType.getMethod().getName());
        if (templates != null) {
            templates.forEach(viewSerializer::filter);
        }
        //读取返回信息
        String responseBody = viewSerializer.writeValueAsString(returnValue);
        //加密处理
        if (request.getAttribute("encryption") != null && (boolean) request.getAttribute("encryption")) {
            logger.info("渠道方返回数据：");
            logger.info(responseBody);
            responseBody = AESUtil.encrypt(responseBody, (String) request.getAttribute("key"));
        }
        response.getWriter().write(responseBody);
        response.getWriter().close();
    }
}
